using System.Runtime.CompilerServices;
#if MYCODE
using BepuUtilities.Vectors;
#else
using System.Numerics;
#endif

namespace BepuUtilities
{
    /// <summary>
    /// 存储3x3矩阵的左下角三角形(包括对角线)。适用于对称矩阵(有时也适用于反对称矩阵)。
    /// </summary>
    public struct Symmetric3x3Wide
    {
        /// <summary>
        /// 矩阵的第一行、第一列。
        /// </summary>
        public Vector<float> XX;
        /// <summary>
        /// 矩阵的第二行,第一列。
        /// </summary>
        public Vector<float> YX;
        /// <summary>
        /// 矩阵的第二行、第二列。
        /// </summary>
        public Vector<float> YY;
        /// <summary>
        /// 矩阵的第三行,第一列。
        /// </summary>
        public Vector<float> ZX;
        /// <summary>
        /// 矩阵的第三行第二列。
        /// </summary>
        public Vector<float> ZY;
        /// <summary>
        /// 矩阵的第三行,第三列。
        /// </summary>
        public Vector<float> ZZ;

        /// <summary>
        /// 将矩阵倒置为对称矩阵,其中m32==m23,m13==m31,m21==m12。
        /// </summary>
        /// <param name="m">要反转的对称矩阵。</param>
        /// 对称矩阵的<param name="Inverse">逆。</param>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static void Invert(in Symmetric3x3Wide m, out Symmetric3x3Wide inverse)
        {
            var xx = m.YY * m.ZZ - m.ZY * m.ZY;
            var yx = m.ZY * m.ZX - m.ZZ * m.YX;
            var zx = m.YX * m.ZY - m.ZX * m.YY;
            var determinantInverse = Vector<float>.One / (xx * m.XX + yx * m.YX + zx * m.ZX);

            var yy = m.ZZ * m.XX - m.ZX * m.ZX;
            var zy = m.ZX * m.YX - m.XX * m.ZY;

            var zz = m.XX * m.YY - m.YX * m.YX;

            inverse.XX = xx * determinantInverse;
            inverse.YX = yx * determinantInverse;
            inverse.ZX = zx * determinantInverse;
            inverse.YY = yy * determinantInverse;
            inverse.ZY = zy * determinantInverse;
            inverse.ZZ = zz * determinantInverse;
        }

        /// <summary>
        /// 将两个对称矩阵的分量相加。
        /// </summary>
        /// <param name="a">要添加的第一个矩阵。</param>
        /// <param name="b">要添加的第二个矩阵。</param>
        /// <param name="result">两个输入矩阵之和。</param>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static void Add(in Symmetric3x3Wide a, in Symmetric3x3Wide b, out Symmetric3x3Wide result)
        {
            result.XX = a.XX + b.XX;
            result.YX = a.YX + b.YX;
            result.YY = a.YY + b.YY;
            result.ZX = a.ZX + b.ZX;
            result.ZY = a.ZY + b.ZY;
            result.ZZ = a.ZZ + b.ZZ;
        }

        /// <summary>
        /// 从一个对称矩阵的分量中减去另一个对称矩阵的分量。
        /// </summary>
        /// <param name="a">要减去的矩阵。</param>
        /// <param name="b">要从第一个矩阵中减去的矩阵。</param>
        /// <param name="result">a-b的结果。</param>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static void Subtract(in Symmetric3x3Wide a, in Symmetric3x3Wide b, out Symmetric3x3Wide result)
        {
            result.XX = a.XX - b.XX;
            result.YX = a.YX - b.YX;
            result.YY = a.YY - b.YY;
            result.ZX = a.ZX - b.ZX;
            result.ZY = a.ZY - b.ZY;
            result.ZZ = a.ZZ - b.ZZ;
        }


        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static void Scale(in Symmetric3x3Wide m, in Vector<float> scale, out Symmetric3x3Wide result)
        {
            result.XX = m.XX * scale;
            result.YX = m.YX * scale;
            result.YY = m.YY * scale;
            result.ZX = m.ZX * scale;
            result.ZY = m.ZY * scale;
            result.ZZ = m.ZZ * scale;
        }
        
        // 如果您需要三角形内底,有几个选择：
        // 对于以下形式的矩阵：
        // [1 0 0]
        // [YX 1 0]
        // [ZX ZY 1]
        // 反之亦然：
        // [1 0 0]
        // M^-1=[-YX 1 0]
        // [YX*ZY-ZX-ZY 1]

        // 对于具有任意对角线(仍是可逆的)的矩阵：
        // [1/XX 0 0]
        // M^-1=[-YX/(XX*YY)1/M22 0]
        // [-(YY*ZX-YX*ZY)/(XX*YY*ZZ)-ZY/(YY*ZZ)1/ZZ]
        // 通过一些调整,你可以使所有的分母都相同,以避免重复除法。

        /// <summary>
        /// 计算对称矩阵m的skewSymmetric(V)*m*转置(skewSymmetric(V))。假定输入和输出矩阵不重叠。
        /// </summary>
        /// <param name="m">对称矩阵。</param>
        /// <param name="v">用于创建用作三明治面包的倾斜对称矩阵的向量。</param>
        /// skewSymmetric(V)*m*转置(skewSymmetric(V))的<param name="三明治">结果。</param>
        /// <remarks>This operation might have a formal name that isn't skew sandwich. But that's okay, its real name is skew sandwich.</remarks>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static void SkewSandwichWithoutOverlap(in Vector3Wide v, in Symmetric3x3Wide m, out Symmetric3x3Wide sandwich)
        {
            // 27个毛姆,15个加。
            var xzy = v.X * m.ZY;
            var yzx = v.Y * m.ZX;
            var zyx = v.Z * m.YX;
            var ixx = yzx - zyx;
            var ixy = v.Y * m.ZY - v.Z * m.YY;
            var ixz = v.Y * m.ZZ - v.Z * m.ZY;
            var iyx = v.Z * m.XX - v.X * m.ZX;
            var iyy = zyx - xzy;
            var iyz = v.Z * m.ZX - v.X * m.ZZ;
            var izx = v.X * m.YX - v.Y * m.XX;
            var izy = v.X * m.YY - v.Y * m.YX;
            var izz = xzy - yzx;

            sandwich.XX = v.Y * ixz - v.Z * ixy;
            sandwich.YX = v.Y * iyz - v.Z * iyy;
            sandwich.YY = v.Z * iyx - v.X * iyz;
            sandwich.ZX = v.Y * izz - v.Z * izy;
            sandwich.ZY = v.Z * izx - v.X * izz;
            sandwich.ZZ = v.X * izy - v.Y * izx;
        }

        /// <summary>
        /// 计算对称矩阵m的v*m*转置(V)。假定输入和输出不重叠。
        /// </summary>
        /// <param name="v">作为三明治面包的矢量。</param>
        /// <param name="m">多肉内部对称矩阵。</param>
        /// 对称矩阵m的v*m*转置(V)的<param name="三明治">结果。</param>
        /// <remarks>Since I called the other one a skew sandwich, I really don't have a choice in the naming convention anymore.</remarks>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static void VectorSandwich(in Vector3Wide v, in Symmetric3x3Wide m, out Vector<float> sandwich)
        {
            // 这实际上并不比等效的显式操作少,但它确实避免了一些结构局部变量,而且这是一个相当常见的操作。
            // (目前,不幸的是,出于代码生成的原因,避免struct本地变量是有帮助的。)
            var x = v.X * m.XX + v.Y * m.YX + v.Z * m.ZX;
            var y = v.X * m.YX + v.Y * m.YY + v.Z * m.ZY;
            var z = v.X * m.ZX + v.Y * m.ZY + v.Z * m.ZZ;
            sandwich = x * v.X + y * v.Y + z * v.Z;
        }

        /// <summary>
        /// 计算对称矩阵m和旋转矩阵R的RT*m*r。
        /// </summary>
        /// <param name="r">用作三明治面包的旋转矩阵。</param>
        /// <param name="m">多肉内部对称矩阵。</param>
        /// 对称矩阵m的v*m*转置(V)的<param name="三明治">结果。</param>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static void RotationSandwich(in Matrix3x3Wide r, in Symmetric3x3Wide m, out Symmetric3x3Wide sandwich)
        {
            var ixx = r.X.X * m.XX + r.Y.X * m.YX + r.Z.X * m.ZX;
            var ixy = r.X.X * m.YX + r.Y.X * m.YY + r.Z.X * m.ZY;
            var ixz = r.X.X * m.ZX + r.Y.X * m.ZY + r.Z.X * m.ZZ;

            var iyx = r.X.Y * m.XX + r.Y.Y * m.YX + r.Z.Y * m.ZX;
            var iyy = r.X.Y * m.YX + r.Y.Y * m.YY + r.Z.Y * m.ZY;
            var iyz = r.X.Y * m.ZX + r.Y.Y * m.ZY + r.Z.Y * m.ZZ;

            var izx = r.X.Z * m.XX + r.Y.Z * m.YX + r.Z.Z * m.ZX;
            var izy = r.X.Z * m.YX + r.Y.Z * m.YY + r.Z.Z * m.ZY;
            var izz = r.X.Z * m.ZX + r.Y.Z * m.ZY + r.Z.Z * m.ZZ;

            sandwich.XX = ixx * r.X.X + ixy * r.Y.X + ixz * r.Z.X;
            sandwich.YX = iyx * r.X.X + iyy * r.Y.X + iyz * r.Z.X;
            sandwich.YY = iyx * r.X.Y + iyy * r.Y.Y + iyz * r.Z.Y;
            sandwich.ZX = izx * r.X.X + izy * r.Y.X + izz * r.Z.X;
            sandwich.ZY = izx * r.X.Y + izy * r.Y.Y + izz * r.Z.Y;
            sandwich.ZZ = izx * r.X.Z + izy * r.Y.Z + izz * r.Z.Z;
        }

        /// <summary>
        /// 假设b表示对称的3x3矩阵,则计算结果=a*b。假设输入参数和输出结果不重叠。
        /// </summary>
        /// <param name="a">要相乘的对的第一个矩阵。</param>
        /// <param name="b">要重新解释为乘法对称的矩阵。</param>
        /// <param name="result">a*b的乘法结果</param>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static void MultiplyWithoutOverlap(in Matrix2x3Wide a, in Symmetric3x3Wide b, out Matrix2x3Wide result)
        {
            result.X.X = a.X.X * b.XX + a.X.Y * b.YX + a.X.Z * b.ZX;
            result.X.Y = a.X.X * b.YX + a.X.Y * b.YY + a.X.Z * b.ZY;
            result.X.Z = a.X.X * b.ZX + a.X.Y * b.ZY + a.X.Z * b.ZZ;
            result.Y.X = a.Y.X * b.XX + a.Y.Y * b.YX + a.Y.Z * b.ZX;
            result.Y.Y = a.Y.X * b.YX + a.Y.Y * b.YY + a.Y.Z * b.ZY;
            result.Y.Z = a.Y.X * b.ZX + a.Y.Y * b.ZY + a.Y.Z * b.ZZ;
        }

        /// <summary>
        /// 假设b表示对称的3x3矩阵,则计算结果=a*b。假设输入参数和输出结果不重叠。
        /// </summary>
        /// <param name="a">要相乘的对的第一个矩阵。</param>
        /// <param name="b">要重新解释为乘法对称的矩阵。</param>
        /// <param name="result">a*b的乘法结果</param>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static void MultiplyWithoutOverlap(in Matrix3x3Wide a, in Symmetric3x3Wide b, out Matrix3x3Wide result)
        {
            result.X.X = a.X.X * b.XX + a.X.Y * b.YX + a.X.Z * b.ZX;
            result.X.Y = a.X.X * b.YX + a.X.Y * b.YY + a.X.Z * b.ZY;
            result.X.Z = a.X.X * b.ZX + a.X.Y * b.ZY + a.X.Z * b.ZZ;

            result.Y.X = a.Y.X * b.XX + a.Y.Y * b.YX + a.Y.Z * b.ZX;
            result.Y.Y = a.Y.X * b.YX + a.Y.Y * b.YY + a.Y.Z * b.ZY;
            result.Y.Z = a.Y.X * b.ZX + a.Y.Y * b.ZY + a.Y.Z * b.ZZ;

            result.Z.X = a.Z.X * b.XX + a.Z.Y * b.YX + a.Z.Z * b.ZX;
            result.Z.Y = a.Z.X * b.YX + a.Z.Y * b.YY + a.Z.Z * b.ZY;
            result.Z.Z = a.Z.X * b.ZX + a.Z.Y * b.ZY + a.Z.Z * b.ZZ;
        }

        /// <summary>
        /// 假设a表示对称的3x3矩阵,则计算结果=a*b。假设输入参数和输出结果不重叠。
        /// </summary>
        /// <param name="a">要重新解释为乘法对称的矩阵。</param>
        /// <param name="b">要相乘的对的第二个矩阵。</param>
        /// <param name="result">a*b的乘法结果</param>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static void Multiply(in Symmetric3x3Wide a, in Matrix3x3Wide b, out Matrix3x3Wide result)
        {
            result.X.X = a.XX * b.X.X + a.YX * b.Y.X + a.ZX * b.Z.X;
            result.X.Y = a.XX * b.X.Y + a.YX * b.Y.Y + a.ZX * b.Z.Y;
            result.X.Z = a.XX * b.X.Z + a.YX * b.Y.Z + a.ZX * b.Z.Z;

            result.Y.X = a.YX * b.X.X + a.YY * b.Y.X + a.ZY * b.Z.X;
            result.Y.Y = a.YX * b.X.Y + a.YY * b.Y.Y + a.ZY * b.Z.Y;
            result.Y.Z = a.YX * b.X.Z + a.YY * b.Y.Z + a.ZY * b.Z.Z;

            result.Z.X = a.ZX * b.X.X + a.ZY * b.Y.X + a.ZZ * b.Z.X;
            result.Z.Y = a.ZX * b.X.Y + a.ZY * b.Y.Y + a.ZZ * b.Z.Y;
            result.Z.Z = a.ZX * b.X.Z + a.ZY * b.Y.Z + a.ZZ * b.Z.Z;
        }

        /// <summary>
        /// 计算结果=a*转置(B)。
        /// </summary>
        /// <param name="a">要与转置后的矩阵相乘的矩阵。</param>
        /// <param name="b">转置并连接第一个矩阵的矩阵。</param>
        /// <param name="result">a*转置(B)的结果。</param>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static void MultiplyByTransposed(in Symmetric3x3Wide a, in Matrix3x3Wide b, out Matrix3x3Wide result)
        {
            result.X.X = a.XX * b.X.X + a.YX * b.X.Y + a.ZX * b.X.Z;
            result.X.Y = a.XX * b.Y.X + a.YX * b.Y.Y + a.ZX * b.Y.Z;
            result.X.Z = a.XX * b.Z.X + a.YX * b.Z.Y + a.ZX * b.Z.Z;

            result.Y.X = a.YX * b.X.X + a.YY * b.X.Y + a.ZY * b.X.Z;
            result.Y.Y = a.YX * b.Y.X + a.YY * b.Y.Y + a.ZY * b.Y.Z;
            result.Y.Z = a.YX * b.Z.X + a.YY * b.Z.Y + a.ZY * b.Z.Z;

            result.Z.X = a.ZX * b.X.X + a.ZY * b.X.Y + a.ZZ * b.X.Z;
            result.Z.Y = a.ZX * b.Y.X + a.ZY * b.Y.Y + a.ZZ * b.Y.Z;
            result.Z.Z = a.ZX * b.Z.X + a.ZY * b.Z.Y + a.ZZ * b.Z.Z;
        }

        /// <summary>
        /// 计算结果=转置(a*转置(B))。
        /// </summary>
        /// <param name="a">要与转置后的矩阵相乘的矩阵。</param>
        /// <param name="b">转置并连接第一个矩阵的矩阵。</param>
        /// <param name="result">转置的结果(a*transspose(B))。</param>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static void MultiplyByTransposed(in Symmetric3x3Wide a, in Matrix2x3Wide b, out Matrix2x3Wide result)
        {
            result.X.X = a.XX * b.X.X + a.YX * b.X.Y + a.ZX * b.X.Z;
            result.Y.X = a.XX * b.Y.X + a.YX * b.Y.Y + a.ZX * b.Y.Z;

            result.X.Y = a.YX * b.X.X + a.YY * b.X.Y + a.ZY * b.X.Z;
            result.Y.Y = a.YX * b.Y.X + a.YY * b.Y.Y + a.ZY * b.Y.Z;

            result.X.Z = a.ZX * b.X.X + a.ZY * b.X.Y + a.ZZ * b.X.Z;
            result.Y.Z = a.ZX * b.Y.X + a.ZY * b.Y.Y + a.ZZ * b.Y.Z;
        }

        /// <summary>
        /// 计算对称矩阵t和矩阵m的m*t*mt。
        /// </summary>
        /// <param name="m">用作三明治面包的矩阵。</param>
        /// <param name="t">多肉内部对称矩阵。</param>
        /// 对称矩阵t的m*t*mt的<param name="三明治">结果。</param>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static void MatrixSandwich(in Matrix2x3Wide m, in Symmetric3x3Wide t, out Symmetric2x2Wide result)
        {
            var ixx = m.X.X * t.XX + m.X.Y * t.YX + m.X.Z * t.ZX;
            var ixy = m.X.X * t.YX + m.X.Y * t.YY + m.X.Z * t.ZY;
            var ixz = m.X.X * t.ZX + m.X.Y * t.ZY + m.X.Z * t.ZZ;
            var iyx = m.Y.X * t.XX + m.Y.Y * t.YX + m.Y.Z * t.ZX;
            var iyy = m.Y.X * t.YX + m.Y.Y * t.YY + m.Y.Z * t.ZY;
            var iyz = m.Y.X * t.ZX + m.Y.Y * t.ZY + m.Y.Z * t.ZZ;
            result.XX = ixx * m.X.X + ixy * m.X.Y + ixz * m.X.Z;
            result.YX = iyx * m.X.X + iyy * m.X.Y + iyz * m.X.Z;
            result.YY = iyx * m.Y.X + iyy * m.Y.Y + iyz * m.Y.Z;
        }

        /// <summary>
        /// 计算结果=a*b,其中a=某个对称矩阵M的转置(B)*M。
        /// </summary>
        /// <param name="a">对于某些对称矩阵M,某些矩阵等于转置(B)*M。</param>
        /// <param name="b">用于夹原始矩阵M的矩阵。</param>
        /// <param name="result">转置(B)*M*b.</param>的完整结果
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static void CompleteMatrixSandwich(in Matrix3x3Wide a, in Matrix3x3Wide b, out Symmetric3x3Wide result)
        {
            // 这些"完成"函数的唯一好处是知道最终结果是对称的,因此不需要计算某些结果。
            // 除此之外,它相当于3x3的乘法。
            result.XX = a.X.X * b.X.X + a.X.Y * b.Y.X + a.X.Z * b.Z.X;

            result.YX = a.Y.X * b.X.X + a.Y.Y * b.Y.X + a.Y.Z * b.Z.X;
            result.YY = a.Y.X * b.X.Y + a.Y.Y * b.Y.Y + a.Y.Z * b.Z.Y;

            result.ZX = a.Z.X * b.X.X + a.Z.Y * b.Y.X + a.Z.Z * b.Z.X;
            result.ZY = a.Z.X * b.X.Y + a.Z.Y * b.Y.Y + a.Z.Z * b.Z.Y;
            result.ZZ = a.Z.X * b.X.Z + a.Z.Y * b.Y.Z + a.Z.Z * b.Z.Z;
        }

        /// <summary>
        /// 对于某些对称矩阵M,计算结果=转置(A)*b,其中a=转置(转置(B)*M)。换句话说,我们只是将矩阵a视为3x2矩阵。
        /// </summary>
        /// <param name="a">对于某些对称矩阵M,某些矩阵等于转置(B)*M。</param>
        /// <param name="b">用于夹原始矩阵M的矩阵。</param>
        /// <param name="result">转置(B)*M*b.</param>的完整结果
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static void CompleteMatrixSandwich(in Matrix2x3Wide a, in Matrix2x3Wide b, out Symmetric3x3Wide result)
        {
            result.XX = a.X.X * b.X.X + a.Y.X * b.Y.X;

            result.YX = a.X.Y * b.X.X + a.Y.Y * b.Y.X;
            result.YY = a.X.Y * b.X.Y + a.Y.Y * b.Y.Y;

            result.ZX = a.X.Z * b.X.X + a.Y.Z * b.Y.X;
            result.ZY = a.X.Z * b.X.Y + a.Y.Z * b.Y.Y;
            result.ZZ = a.X.Z * b.X.Z + a.Y.Z * b.Y.Z;
        }

        /// <summary>
        /// 计算结果=a*转置(B),其中对于某个对称矩阵M,a=b*M。
        /// </summary>
        /// <param name="a">对于某些对称矩阵M,某些矩阵等于b*M。</param>
        /// <param name="b">用于夹住要转置的原始矩阵M的矩阵。</param>
        /// <param name="result">b*M*转置(B)的完整结果。</param>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static void CompleteMatrixSandwichByTranspose(in Matrix3x3Wide a, in Matrix3x3Wide b, out Symmetric3x3Wide result)
        {
            result.XX = a.X.X * b.X.X + a.X.Y * b.X.Y + a.X.Z * b.X.Z;

            result.YX = a.Y.X * b.X.X + a.Y.Y * b.X.Y + a.Y.Z * b.X.Z;
            result.YY = a.Y.X * b.Y.X + a.Y.Y * b.Y.Y + a.Y.Z * b.Y.Z;

            result.ZX = a.Z.X * b.X.X + a.Z.Y * b.X.Y + a.Z.Z * b.X.Z;
            result.ZY = a.Z.X * b.Y.X + a.Z.Y * b.Y.Y + a.Z.Z * b.Y.Z;
            result.ZZ = a.Z.X * b.Z.X + a.Z.Y * b.Z.Y + a.Z.Z * b.Z.Z;
        }

        /// <summary>
        /// 计算结果=转置(A)*b,其中b=某个对称矩阵M的M*a。
        /// </summary>
        /// <param name="a">用于夹原始矩阵M的矩阵</param>
        /// <param name="b">对于某些对称矩阵M,某些矩阵等于M*a。</param>
        /// <param name="result">转置(A)*M*a的完整结果。</param>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static void CompleteMatrixSandwichTranspose(in Matrix3x3Wide a, in Matrix3x3Wide b, out Symmetric3x3Wide result)
        {
            result.XX = a.X.X * b.X.X + a.Y.X * b.Y.X + a.Z.X * b.Z.X;

            result.YX = a.X.Y * b.X.X + a.Y.Y * b.Y.X + a.Z.Y * b.Z.X;
            result.YY = a.X.Y * b.X.Y + a.Y.Y * b.Y.Y + a.Z.Y * b.Z.Y;

            result.ZX = a.X.Z * b.X.X + a.Y.Z * b.Y.X + a.Z.Z * b.Z.X;
            result.ZY = a.X.Z * b.X.Y + a.Y.Z * b.Y.Y + a.Z.Z * b.Z.Y;
            result.ZZ = a.X.Z * b.X.Z + a.Y.Z * b.Y.Z + a.Z.Z * b.Z.Z;
        }        

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static void TransformWithoutOverlap(in Vector3Wide v, in Symmetric3x3Wide m, out Vector3Wide result)
        {
            result.X = v.X * m.XX + v.Y * m.YX + v.Z * m.ZX;
            result.Y = v.X * m.YX + v.Y * m.YY + v.Z * m.ZY;
            result.Z = v.X * m.ZX + v.Y * m.ZY + v.Z * m.ZZ;
        }

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static void WriteFirst(in Symmetric3x3 scalar, ref Symmetric3x3Wide wide)
        {
            GatherScatter.GetFirst(ref wide.XX) = scalar.XX;
            GatherScatter.GetFirst(ref wide.YX) = scalar.YX;
            GatherScatter.GetFirst(ref wide.YY) = scalar.YY;
            GatherScatter.GetFirst(ref wide.ZX) = scalar.ZX;
            GatherScatter.GetFirst(ref wide.ZY) = scalar.ZY;
            GatherScatter.GetFirst(ref wide.ZZ) = scalar.ZZ;
        }
    }
}
